package com.hackathon2012_03_04.ryokocial;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sun.misc.GC.LatencyRequest;

import com.hackathon2012_03_04.ryokocial.ThumbnailService.Size;

public class SearchServlet extends HttpServlet{
	private static final ThumbnailService thumbnailService
    = new ThumbnailServiceImpl();
	
	//private static final String BASE_URL="http://localhost:8888/";
	private static final String BASE_URL="http://ryokocial-test.appspot.com";
	//private static final String BASE_URL="http://ryokocial.appspot.com";
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
    	
        // パラメータ解決
        Long id = null;
        String size = null;
        String picname=null;
        String keyword=null;
        String travel=null;
        double hereLat=0;
        double hereLng=0;
        
        String order=null;
        
        try {
            id = Long.valueOf( req.getParameter( "id" ) );
        } catch ( NumberFormatException e ) {
            resp.setStatus(404);
            return;
        }
        
        try {
            String str = req.getParameter( "size" );
            if (str != null) size = str;
            req.setAttribute("size", size);
        } catch (IllegalArgumentException e) {}
        
        try {
            String str = req.getParameter( "picname" );
            if (str != null) picname = req.getParameter( "picname" );
            req.setAttribute("picname",picname );
        } catch (IllegalArgumentException e) {}
        
        try {
            String str = req.getParameter( "kayword" );
            if (str != null) keyword = req.getParameter( "kayword" );
            req.setAttribute("keyword",keyword );
        } catch (IllegalArgumentException e) {}
        
        try {
            String str = req.getParameter( "travel" );
            if (str != null) travel = req.getParameter( "travel" );
            req.setAttribute("travel",travel );
        } catch (IllegalArgumentException e) {}
        
        try {
            String str = req.getParameter( "lat" );
            if (str != null) hereLat = Double.parseDouble(req.getParameter( "lat" ));
            req.setAttribute("lat",hereLat );
        } catch (IllegalArgumentException e) {}
        
        try {
            String str = req.getParameter( "lng" );
            if (str != null) hereLng = Double.parseDouble(req.getParameter( "lng" ));
            req.setAttribute("lng",hereLat );
        } catch (IllegalArgumentException e) {}
        
        try {
            String str = req.getParameter( "order" );
            if (str != null) order = req.getParameter( "order" );
        } catch (IllegalArgumentException e) {}
        
        //入力チェック
        if((keyword == null || keyword.equals(""))
        		&& (hereLat == 0)
        		&& (hereLng == 0)
        		){
        	RequestDispatcher dispatcher = 
        			getServletContext().getRequestDispatcher("/search.jsp");
        	
        	req.setAttribute("error", true);
        	dispatcher.forward(req, resp);
        	return;
        }
        
        ArrayList<Long> searchedId=new ArrayList<Long>();
        ArrayList<Double> searchedLat=new ArrayList<Double>();
        ArrayList<Double> searchedLng=new ArrayList<Double>();
        
        //検索
        List<Thumbnail> thumbnails=thumbnailService.search(keyword,0);
        
        //旅行一単位で検索
        if((keyword == null || keyword.equals(""))
        		&& (picname == null || picname.equals(""))
        		&& (hereLat == 0)
        		&& (hereLng == 0)
        		&& (travel != null)
        		){
        	thumbnails=thumbnailService.search(travel,1);
        }
        	
        //検索結果から、各属性を取得
        for(Thumbnail item:thumbnails){
        	System.out.println("-----------------------------------------------");
        	System.out.println(item.getId());
        	searchedId.add(item.getId());
        	
        	System.out.println(item.getCaption());
        	System.out.println(item.getUser());
        	System.out.println(item.getTags());
        	ArrayList<String> tags=new ArrayList<String>();
        	for(String tag:item.getTags()){
        		tags.add(tag);
        	}
        	
        	System.out.println(item.getLat());
        	searchedLat.add(item.getLat());
        	System.out.println(item.getLng());
        	searchedLng.add(item.getLng());
        	System.out.println("-----------------------------------------------");
        }
        
        ArrayList<Double> dist=new ArrayList<Double>();
        ArrayList<Date> dates=new ArrayList<Date>();
        if(order != null && order.equals("nearest")){
        	//位置情報検索
            //位置情報で検索することがウマク出来なかったので、全件取得してから位置を取得、絞り込みを行う。
            //TODO　GeoHash使えば出来るはず・・・。
            if(hereLat !=0 && hereLng != 0 ){
            	System.out.println("Order Geo");
            	searchedId.clear();
            	hereLat*=111.263;
            	hereLng*=91.159;
            	for(int i=0;i<thumbnails.size();i++){
            		//緯度経度を、距離に直してます
            		//
            		double lat=searchedLat.get(i)*111.263;
            		double lng=searchedLng.get(i)*91.159;
        		
            		double dLat2=(lat-hereLat)*(lat-hereLat);
            		double dLng2=(lng-hereLng)*(lng-hereLng);
            		double r=Math.sqrt(dLat2+dLng2);
            		if(r<10){
            			searchedId.add(thumbnails.get(i).getId());
            			//TODO 現在地からの距離で並び替えたいなら、rの値でソートする。
            			dist.add(r);
            		}
            	}
            }
            if(dist.size()>0){
            	// sort
            	long[] l=new long[searchedId.size()];
            	double[] d=new double[dist.size()];
            	for(int i=0;i<searchedId.size();i++){
            		l[i]=searchedId.get(i);
            		d[i]=dist.get(i);
            	}
                for (int i = 0; i < l.length; i++) {// 0, 1, ... len  
                    for (int j = i + 1; j < l.length; j++) {// i+1, ... len  
                        if (d[i] > d[j]) {    //昇順
                            swapValue(l,d, i, j);
                        }
                    }  
                }  
                searchedId.clear();
                dist.clear();
                for(int i=0;i<l.length;i++){
                	searchedId.add(l[i]);
                	dist.add(d[i]);
                }
            }
        }else if(order != null && order.equals("date")){
        	//TODO
        	System.out.println("");
        	searchedId.clear();
        	for(Thumbnail item:thumbnails){
        		//TODO
        	}
        }
        
        
        
        
		//
        //req.setAttribute("length", searchedId.size());
		//req.setAttribute("ids", searchedId);
		//req.setAttribute("searchedTags", searchedTags);
		
		resp.setContentType("application/json; charset=utf-8");
		resp.setHeader("Access-Control-Allow-Origin", "*");  
		resp.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE, OPTIONS");
		
		// サムネイルの取り出しと出力
		String json=null;
		StringBuffer sb=new StringBuffer();
		sb.append("[");
		String callback = req.getParameter("callback");
		for(int n=0;n<searchedId.size();n++){
			Long l=searchedId.get(n);
			Thumbnail thumbnail = thumbnailService.getById(l);
			
			sb.append("{\"image\":\""+BASE_URL+"/thumbnail?id="+l+"&size=small\"");
			sb.append(",\"thumbnail\":\""+BASE_URL+"/thumbnail?id="+l+"&size=original\"");
			sb.append(",\"id\":"+thumbnail.getId());
			sb.append(",\"lat\":"+thumbnail.getLat());
			sb.append(",\"lng\":"+thumbnail.getLng());
			sb.append(",\"caption\":\""+thumbnail.getCaption()+"\"");
			sb.append(",\"user\":\""+thumbnail.getUser()+"\"");
			sb.append(",\"createDate\":\""+thumbnail.getCreateDate()+"\"");
			if(dist.size()>0){
				sb.append(",\"dist\":"+dist.get(n));
			}
			sb.append(",\"tags\":[");
			for(int i=0;i<thumbnail.getTags().size();i++){
				sb.append("\""+thumbnail.getTags().get(i)+"\"");
				if(i<(thumbnail.getTags().size()-1)){
					sb.append(",");
				}
			}
			sb.append("]}");
			if(n != (searchedId.size()-1)){
				sb.append(",");
			}
		}
		sb.append("]");
		json=new String(sb);
		resp.getWriter().print(String.format("%s(%s)", callback, json));
        /*
        RequestDispatcher dispatcher=req.getRequestDispatcher("/WEB-INF/disp.jsp");
        
        dispatcher.forward(req, resp);
        */
	}
	
	/* 
     * バブルソート 
     * @param x ソート対象となる配列 
     * @param asc true:昇順, false:降順 
     * @return ソート後の配列 
     */  
    private static void bubbleSort( boolean asc) { 
    	
    }  
    /* 
     * 指定する配列のx[i],x[j]の値を置換する  
     * @param x 配列  
     * @param i 位置  
     * @param j 位置 
     */  
    private static void swapValue(long[] l,double[] d,int i, int j) {  
        long tmpl = l[i]; // x[i]→tmp  
        l[i] = l[j];     // x[j]→x[i]  
        l[j] = tmpl;     // tmp→x[j]  
        
        double tmpd = d[i]; // x[i]→tmp  
        d[i] = d[j];     // x[j]→x[i]  
        d[j] = tmpd;     // tmp→x[j]  
    }  
}
